package com.didd.core.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;

import static java.lang.String.format;

/**
 * bean工具类
 * 测试了10万次内, hutool性能更优
 *
 * @author diddd
 * @date 2019/07/15
 */
@Slf4j
public class BeanUtil extends cn.hutool.core.bean.BeanUtil {
    private static final String FORMAT_MASSAGE = "Create new instance of %s failed: %s";

    /**
     * 反射copy bean实体
     *
     * @param source 源
     * @param target 目标对象
     * @return target对象
     */
    public static <T> T copy(Object source, Class<T> target) {
        if (source == null) {
            return null;
        }
        try {
            T t = target.newInstance();
            copyProperties(source, t);
            return t;
        } catch (Exception ex) {
            // log.error("BeanUtil.copy", e);
            //解决 source和target 属性类型不一样报错
            return springCopyBean(source, target);
        }
    }


    /**
     * 反射copy bean实体
     *
     * @param source 源
     * @param target 目标对象
     * @return target对象
     */
    public static <T> T copy(Class<T> target, Object... source) {
        if (source == null) {
            return null;
        }
        T t = null;
        try {
            t = target.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(format(FORMAT_MASSAGE, target, e.getMessage()));
        }
        try {
            for (Object obj : source) {
                if (obj == null) {
                    continue;
                }
                copyProperties(obj, t);
            }
            return t;
        } catch (Exception ex) {
            // log.error("BeanUtil.copy", e);
            //解决 source和target 属性类型不一样报错
            for (Object obj : source) {
                if (obj == null) {
                    continue;
                }
                BeanUtils.copyProperties(obj, t);
            }
            return t;
        }
    }


    /**
     * 返回copy bean list
     *
     * @param sources 源
     * @param target  目标对象
     * @return List<target>对象
     */
    public static <T> List<T> copyList(List<? extends Object> sources, Class<T> target) {
        if (sources == null || sources.isEmpty()) {
            return null;
        }
        List<T> beanList = new ArrayList<>();
        for (Object source : sources) {
            beanList.add(copy(source, target));
        }
        return beanList;
    }


    /**
     * extends Spring Beans
     *
     * @param source
     * @param targetClass
     * @param <T>
     * @return
     */
    private static <T> T springCopyBean(Object source, Class<T> targetClass) {
        if (null == source) {
            return null;
        }

        T t;
        try {
            t = targetClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(format(FORMAT_MASSAGE, targetClass, e.getMessage()));
        }
        BeanUtils.copyProperties(source, t);
        return t;
    }
}
